<script lang="ts" setup>
import {
    Button,
    Form,
    Input,
    Select,
    Switch,
    Tooltip,
    message,
    Row,
    Col,
} from 'ant-design-vue'
import { type AfterFetchContext, objectOmit } from '@vueuse/core'
import {
    type IStressCase,
    type IStressCaseAssertion,
    type IStressCaseRelation,
    type IStressCaseThreadGroupConfig,
    type IStressCaseDetailSaveReq,
    defaultWithIStressCase,
    defaultWithIStressCaseRelation,
    defaultWithIStressCaseThreadGroupConfig,
    defaultWithIStressCaseDetailSaveReq
} from '~/types/apis/stress-case'
import type { IDict } from '~/types/apis/dict'
import type { ComponentExposed } from 'vue-component-type-helpers'
import type NewOrEditBodyVue from '~/components/NewOrEdit/NewOrEditBody.vue'
import type { IBasic } from '~/types/apis/basic'
import type { ColumnsType } from 'ant-design-vue/es/table'
import type StressTestInterfaceConfig from '~/components/StressTest/StressTestInterfaceConfig.vue'
import type StressTestSamplerConfig from '~/components/StressTest/StressTestSamplerConfig.vue'
import type RequestConfigVue from '~/components/NewOrEdit/RequestConfig.vue'

const formModelExpand = reactive<{
    relation: boolean
    assertion: boolean
    relationData: IStressCaseRelation[]
    assertionData: IStressCaseAssertion[]
    threadGroupConfig: IStressCaseThreadGroupConfig
}>({
    relation: false,
    assertion: false,
    relationData: [],
    assertionData: [],
    threadGroupConfig: { ...defaultWithIStressCaseThreadGroupConfig },
})

const router = useRouter()
let stressCaseDetailSaveReq = Object.assign({}, defaultWithIStressCaseDetailSaveReq)
const formModel = ref<IStressCase>({ ...defaultWithIStressCase })
const bodyRef = ref<ComponentExposed<typeof NewOrEditBodyVue>>()
const beforeInterfaceConfigRef = ref<ComponentExposed<typeof StressTestInterfaceConfig>>()
const ordinaryInterfaceConfigRef = ref<ComponentExposed<typeof StressTestInterfaceConfig>>()
const argumentsDataSource = ref<object[]>([])

const relationColumns: ColumnsType = [
    {
        title: '名称',
        dataIndex: 'name',
        key: 'name',
        align: 'center',
    },
    {
        title: '文件类型',
        dataIndex: 'sourceType',
        key: 'sourceType',
        align: 'center',
    },
    {
        title: '分隔符',
        dataIndex: 'delimiter',
        key: 'delimiter',
        align: 'center',
    },
    {
        title: '是否忽略首行',
        dataIndex: 'ignoreFirstLine',
        key: 'ignoreFirstLine',
        align: 'center',
    },
    {
        title: '循环读取',
        dataIndex: 'recycle',
        key: 'recycle',
        align: 'center',
    },
    {
        title: '变量名称 (逗号分割)',
        dataIndex: 'variableNames',
        key: 'variableNames',
        align: 'center',
    },
    {
        title: '文件上传',
        dataIndex: 'fileUpload',
        key: 'fileUpload',
        align: 'center',
    },
    {
        title: '操作',
        dataIndex: 'operator',
        align: 'center',
        key: 'operator',
    },
]


const { data: fetchDictListData } = useCustomFetch<Record<string, IDict[]>>(
    '/engine-service/api/v1/dict/list?category=stress_assert_action,stress_assert_from,stress_source_type',
    {
        afterFetch(ctx: AfterFetchContext<IBasic<Record<string, IDict[]>>>) {
            if (ctx.data && ctx.data.code === 0) {
                return {
                    data: ctx.data.data,
                    response: ctx.response,
                }
            }
            return {
                data: [],
                response: ctx.response,
            }
        },
    },
)

const { post: fetchCreateStressCase } = useCustomFetch(
    '/engine-service/api/v1/stress_case/save',
    {
        immediate: false,
        afterFetch(ctx: AfterFetchContext<IBasic>) {
            if (ctx.data && ctx.data.code === 0) {
                message.success('保存成功')
                router.back()
            }
            return ctx
        },
    },
)

const { put: fetchUpdateStressCase } = useCustomFetch(
    '/engine-service/api/v1/stress_case/update',
    {
        immediate: false,
        afterFetch(ctx: AfterFetchContext<IBasic>) {
            if (ctx.data && ctx.data.code === 0) {
                message.success('更新成功')
                router.back()
            }
            return ctx
        },
    },
)

function handleAddRelation(index?: number) {
    if (formModel.value.stressSourceType.toUpperCase() === 'SIMPLE') {
        formModel.value.stressCaseDetailSaveReqList[index].formModelExpand.relationData.push({ ...defaultWithIStressCaseRelation })
    } else {
        formModelExpand.relationData.push({ ...defaultWithIStressCaseRelation })
    }
}
function handleSave() {
    const formData = ref({})
    formData.value = JSON.parse(JSON.stringify(formModel.value))
    if (formModel.value.stressSourceType.toUpperCase() === 'SIMPLE') {

        if (argumentsDataSource.value.length > 0) {
            formData.value.arguments = objectSerializer(argumentsDataSource.value).replace(
                /"name":/g,
                `"key":`,
            )
        }
        formData.value.threadGroupConfig = objectSerializer<
            IStressCaseThreadGroupConfig,
            false
        >(formModelExpand.threadGroupConfig)
        formData.value.stressCaseDetailSaveReqList.map((item: IStressCaseDetailSaveReq, index: number) => {
            // 参数
            item.relation = objectSerializer<IStressCaseRelation[], false>(
                item.formModelExpand.relationData,
            )
            // 断言
            item.assertion = objectSerializer<IStressCaseAssertion[], false>(
                item.formModelExpand.assertionData,
            )
            // 删除接口所需的多于字段，该字段用户前端页面逻辑
            delete item?.formModelExpand
        })
        beforeInterfaceConfigRef.value?.beforeRequestConfigRefList.map((item: { el: ComponentExposed<typeof RequestConfigVue>, index: number }) => {
            const index = formData.value.stressCaseDetailSaveReqList.findIndex((f: IStressCaseDetailSaveReq) => f.index === item.index)
            if (formData.value.stressCaseDetailSaveReqList[index].interfaceType === 'BEFORE') {
                const { body, header, query, relation } = item.el?.serialize() ?? {}
                formData.value.stressCaseDetailSaveReqList[index].header = header ?? ''
                formData.value.stressCaseDetailSaveReqList[index].query = query ?? ''
                formData.value.stressCaseDetailSaveReqList[index].body = body ?? ''
                formData.value.stressCaseDetailSaveReqList[index].relationParam = relation ?? ''
            }

        })
        ordinaryInterfaceConfigRef.value?.ordinaryRequestConfigRefList.map((item: { el: ComponentExposed<typeof RequestConfigVue>, index: number }) => {
            const index = formData.value.stressCaseDetailSaveReqList.findIndex((f: IStressCaseDetailSaveReq) => f.index === item.index)
            if (formData.value.stressCaseDetailSaveReqList[index].interfaceType === 'ORDINARY') {
                const { body, header, query } = item.el?.serialize() ?? {}
                formData.value.stressCaseDetailSaveReqList[index].header = header ?? ''
                formData.value.stressCaseDetailSaveReqList[index].query = query ?? ''
                formData.value.stressCaseDetailSaveReqList[index].body = body ?? ''
            }
        })

        // 如果是编辑压测详情内容 stressCaseDetailSaveReqList需修改为stressCaseDetailUpdateReqList字段
        if (bodyRef.value?.isEditState) {
            formData.value.stressCaseDetailUpdateReqList = formData.value.stressCaseDetailSaveReqList
            delete formData.value.stressCaseDetailSaveReqList
        }

    } else if (formModel.value.stressSourceType.toUpperCase() === 'JMX') {
        if (formModelExpand.relation) {
            formData.value.relation = objectSerializer<IStressCaseRelation[], false>(
                formModelExpand.relationData,
            )
        } else {
            formData.value.relation = ''
        }
    }
    console.log('formData.value-->', formData.value);

    if (!bodyRef.value?.isEditState) {
        fetchCreateStressCase(objectOmit(formData.value, ['id'])).execute()
    } else {
        fetchUpdateStressCase(formData.value).execute()
    }
}

async function deserialize() {
    await nextTick()

    if (formModel.value.stressSourceType.toUpperCase() === 'SIMPLE') {
        if (formModel.value.arguments) {
            argumentsDataSource.value = objectDeserializer(
                formModel.value.arguments
            )
        }

        // 线程配置赋值
        formModelExpand.threadGroupConfig = objectDeserializer<
            IStressCaseThreadGroupConfig,
            false
        >(formModel.value.threadGroupConfig, false)

        // 因详情接口返回数据和保存或者修改接口不一致，因此在这里修改，使字段保持一致
        formModel.value.stressCaseDetailSaveReqList = formModel.value.stressCaseDetailDTOList
        delete formModel.value.stressCaseDetailDTOList
        formModel.value.stressCaseDetailSaveReqList.map((item: IStressCaseDetailSaveReq, index: number) => {
            item.index = index;
            item.formModelExpand = JSON.parse(JSON.stringify(formModelExpand))
            // 参数列表赋值
            if (item.relation != "[]") {
                item.formModelExpand.relation = true
                item.formModelExpand.relationData = objectDeserializer<
                    IStressCaseRelation[],
                    false
                >(item.relation, false)
            }
            // 断言列表赋值
            if (item.assertion != "[]") {
                item.formModelExpand.assertion = true
                item.formModelExpand.assertionData = objectDeserializer<
                    IStressCaseAssertion[],
                    false
                >(item.assertion, false)
            }
        })
        // 给请求参数赋值
        // const beforeData = formModel.value.stressCaseDetailSaveReqList.filter((item: IStressCaseDetailSaveReq) => item.interfaceType == 'BEFORE')
        // const ordinaryData = formModel.value.stressCaseDetailSaveReqList.filter((item: IStressCaseDetailSaveReq) => item.interfaceType == 'ORDINARY')
        // if (beforeData.length > 0) {
        //     beforeInterfaceConfigRef.value.requestDeserialize(beforeInterfaceConfigRef.value.beforeRequestConfigRefList[0].el, beforeData[0])
        // }
        // if (ordinaryData.length > 0) {
        //     ordinaryInterfaceConfigRef.value.requestDeserialize(ordinaryInterfaceConfigRef.value.ordinaryRequestConfigRefList[0].el, ordinaryData[0])
        // }
    } else {
        if (formModel.value.relation) {
            formModelExpand.relation = true
            formModelExpand.relationData = objectDeserializer<
                IStressCaseRelation[],
                false
            >(formModel.value.relation, false)
        }
    }
}

watch(() => formModel.value.stressSourceType, (newVal: string) => {
    if (newVal === 'SIMPLE') {
        if (formModel.value.arguments) {
            argumentsDataSource.value = objectDeserializer(
                formModel.value.arguments,
            )
        }
        const formModelExpand2 = JSON.parse(JSON.stringify(formModelExpand))
        stressCaseDetailSaveReq.formModelExpand = formModelExpand2
        stressCaseDetailSaveReq.index = 0
        // const stressCaseDetailSaveReq2 = JSON.parse(JSON.stringify(stressCaseDetailSaveReq))
        // Object.assign(stressCaseDetailSaveReq2, { interfaceType: 'BEFORE', index: 0 })
        formModel.value.stressCaseDetailSaveReqList = [stressCaseDetailSaveReq,]
        // console.log('watch-->', formModel.value.stressCaseDetailSaveReqList);

    } else {
        formModel.value.stressCaseDetailSaveReqList = []
    }
}, { deep: true })
</script>

<template>
    <div>
        <NewOrEditBody ref="bodyRef" v-model:form-model="formModel" @deserialize="deserialize" caseType="stress">
            <Form :modal="formModel" layout="vertical" mx-5>

                <Row :gutter="45">
                    <Col :span="12">
                    <Form.Item label="选择压测类型：">
                        <Select v-model:value="formModel.stressSourceType">
                            <Select.Option v-for="item in fetchDictListData?.stress_source_type" :key="item.id"
                                :value="item.value.toUpperCase()">
                                <Tooltip :title="item.remark">
                                    {{ item.name }}
                                </Tooltip>
                            </Select.Option>
                        </Select>
                    </Form.Item>
                    </Col>
                    <Col :span="12">
                    <Form.Item label="用例名称：">
                        <Input v-model:value="formModel.name" />
                    </Form.Item>
                    </Col>
                </Row>
                <Row :gutter="45">
                    <Col :span="12">
                    <Form.Item label="用例描述：">
                        <Input v-model:value="formModel.description" />
                    </Form.Item>
                    </Col>
                    <Col :span="12">
                    <FormItemEnvironment v-if="formModel.stressSourceType.toUpperCase() !== 'JMX'"
                        v-model:environmentId="formModel.environmentId" label-name="选择环境：" />
                    </Col>
                </Row>
                <Form.Item v-if="formModel.stressSourceType.toUpperCase() === 'JMX'" label="上传 JMX 脚本：">
                    <UploadFile :show-url="formModel.jmxUrl" @change="
                        $event.file.response &&
                        (formModel.jmxUrl = $event.file.response.data)
                        ">
                        <Button>{{ !!formModel.jmxUrl ? '已上传' : '未上传' }}</Button>
                    </UploadFile>
                </Form.Item>

                <template v-if="formModel.stressSourceType.toUpperCase() === 'SIMPLE'">
                    <Form.Item label="线程组配置：">
                        <div b="~ solid #707070 op-75" mx-8 rounded p="x-6 t-6">
                            <Form :modal="formModelExpand.threadGroupConfig" size="small" layout="vertical"
                                grid="~ cols-4 gap-4">
                                <Form.Item label="线程组名称：">
                                    <Input v-model:value="formModelExpand.threadGroupConfig.threadGroupName
                                        " />
                                </Form.Item>
                                <Form.Item label="并发数量：">
                                    <Input v-model:value="formModelExpand.threadGroupConfig.numThreads" type="number" />
                                </Form.Item>
                                <Form.Item label="启动时间（秒）：">
                                    <Input v-model:value="formModelExpand.threadGroupConfig.rampUp" type="number" />
                                </Form.Item>
                                <Form.Item label="循环次数：">
                                    <Input v-model:value="formModelExpand.threadGroupConfig.loopCount" type="number" />
                                </Form.Item>
                                <Form.Item label="是否开启调度器：">
                                    <Switch v-model:checked="formModelExpand.threadGroupConfig.schedulerEnabled"
                                        size="default" />
                                </Form.Item>
                                <Form.Item label="持续时间（秒）：">
                                    <Input v-model:value="formModelExpand.threadGroupConfig.duration" :disabled="!formModelExpand.threadGroupConfig.schedulerEnabled
                                        " type="number" />
                                </Form.Item>
                                <Form.Item label="启动延迟（秒）：">
                                    <Input v-model:value="formModelExpand.threadGroupConfig.delay" :disabled="!formModelExpand.threadGroupConfig.schedulerEnabled
                                        " type="number" />
                                </Form.Item>
                            </Form>
                        </div>
                    </Form.Item>
                    <Form.Item label="全局参数：">
                        <div b="~ solid #707070 op-75" mx-8 rounded p="x-6 t-6" class="global-params">
                            <PairTable v-model:data-source="argumentsDataSource" key-name="fieldName" key-title="key"
                                value-name="fieldValue" value-title="value" :showPagination="false" />
                        </div>

                    </Form.Item>
                    <StressTestInterfaceConfig ref="beforeInterfaceConfigRef" v-model:formModel="formModel"
                        interfaceType="BEFORE" />
                    <StressTestInterfaceConfig ref="ordinaryInterfaceConfigRef" v-model:formModel="formModel"
                        interfaceType="ORDINARY" />
                    <StressTestSamplerConfig v-model:formModel="formModel"  />
                </template>

                <template v-else>
                    <Form.Item label="开启参数化：">
                        <Switch v-model:checked="formModelExpand.relation" />
                    </Form.Item>

                    <template v-if="formModelExpand.relation">
                        <EditableTable v-model:data-source-proxy="formModelExpand.relationData" :columns="relationColumns"
                            :custom-fields="[
                                'ignoreFirstLine',
                                'recycle',
                                'fileUpload',
                                'sourceType',
                            ]" @add-data="handleAddRelation(index)">
                            <template #bodyCell="{ column, isEdit, record, currentEditableInstance }">
                                <template v-if="column.key === 'fileUpload'">
                                    <UploadFile v-if="isEdit" :show-url="record?.['remoteFilePath']" @change="
                                        $event.file.response &&
                                        (currentEditableInstance.remoteFilePath =
                                            $event.file.response.data)
                                        ">
                                        <Button type="link">{{
                                            !!record?.['remoteFilePath'] ? '已上传' : '上传文件'
                                        }}</Button>
                                    </UploadFile>
                                    <span v-else>{{
                                        !!record?.['remoteFilePath'] ? '已上传' : '未上传'
                                    }}</span>
                                </template>
                            </template>
                        </EditableTable>
                    </template>
                </template>


            </Form>
        </NewOrEditBody>
        <NewOrEditFooter name="接口" @save="handleSave" />
    </div>
</template>


<style scoped>
.global-params {
    height: 400px;
    overflow-y: auto;
}

.global-params::-webkit-scrollbar {
    width: 8px;
    /* 滚动条宽度 */
    height: 8px;
    /* 对于水平滚动条，设置高度 */

    background-color: transparent;
    /* 滚动条背景色 */
}

/* 自定义滚动条滑块样式 */
.global-params::-webkit-scrollbar-thumb {
    background-color: var(--scrollbar-bg);
    /* 滑块背景色 */
    border-radius: 8px;
    /* 滑块圆角 */
}

/* 自定义滚动条轨道样式 */
.global-params::-webkit-scrollbar-track {
    background-color: transparent;
    /* 轨道背景色 */
}


/* 定义当滑块悬停或活动时的样式 */
.global-params::-webkit-scrollbar-thumb:hover {
    background: var(--scrollbar-hover-bg);
    /* 滑块悬停颜色 */
}

.global-params::-webkit-scrollbar-corner {
    background: transparent !important;
}
</style>